Dowiedz si臋, jak tworzy膰 pot臋偶ne punkty ko艅cowe API za pomoc膮 Next.js Route Handlers. Ten przewodnik omawia wszystko, od podstawowej konfiguracji po zaawansowane techniki, z praktycznymi przyk艂adami i najlepszymi praktykami.
Next.js Route Handlers: Kompleksowy przewodnik po tworzeniu punkt贸w ko艅cowych API
Next.js zrewolucjonizowa艂 spos贸b, w jaki tworzymy aplikacje internetowe, dzi臋ki swoim pot臋偶nym funkcjom, takim jak renderowanie po stronie serwera, generowanie statycznych stron, a teraz tak偶e Route Handlers. Route Handlers zapewniaj膮 elastyczny i wydajny spos贸b tworzenia punkt贸w ko艅cowych API bezpo艣rednio w aplikacji Next.js. Ten przewodnik omawia koncepcj臋 Route Handlers, ich zalety oraz sposoby ich efektywnego wykorzystania do budowy solidnych interfejs贸w API.
Czym s膮 Next.js Route Handlers?
Route Handlers to funkcje zdefiniowane w katalogu app projektu Next.js, kt贸re obs艂uguj膮 przychodz膮ce 偶膮dania HTTP. W przeciwie艅stwie do starszego podej艣cia pages/api (kt贸re u偶ywa API Routes), Route Handlers oferuj膮 bardziej usprawniony i elastyczny spos贸b definiowania punkt贸w ko艅cowych API obok komponent贸w React. S膮 to w zasadzie funkcje bezserwerowe wykonywane na brzegu sieci (edge) lub w wybranym 艣rodowisku serwerowym.
Mo偶na my艣le膰 o Route Handlers jako o logice backendowej aplikacji Next.js, odpowiedzialnej za przetwarzanie 偶膮da艅, interakcj臋 z bazami danych i zwracanie odpowiedzi.
Korzy艣ci z u偶ywania Route Handlers
- Kolokacja: Route Handlers znajduj膮 si臋 bezpo艣rednio obok komponent贸w React w katalogu
app, co sprzyja lepszej organizacji i utrzymaniu kodu. - Wsparcie dla TypeScript: Wbudowane wsparcie dla TypeScript zapewnia bezpiecze艅stwo typ贸w i poprawia do艣wiadczenie deweloperskie.
- Integracja z Middleware: 艁atwa integracja z middleware do zada艅 takich jak uwierzytelnianie, autoryzacja i walidacja 偶膮da艅.
- Wsparcie dla streamingu: Route Handlers mog膮 przesy艂a膰 dane strumieniowo, umo偶liwiaj膮c stopniowe wysy艂anie odpowiedzi, co jest korzystne w przypadku du偶ych zbior贸w danych lub d艂ugotrwa艂ych proces贸w.
- Funkcje brzegowe (Edge Functions): Wdra偶aj Route Handlers jako funkcje brzegowe (Edge Functions) dla odpowiedzi o niskim op贸藕nieniu, bli偶ej u偶ytkownik贸w, wykorzystuj膮c globalne sieci CDN.
- Uproszczony projekt API: Route Handlers zapewniaj膮 czyste i intuicyjne API do obs艂ugi 偶膮da艅 i odpowiedzi.
- Integracja z Server Actions: 艢cis艂a integracja z Server Actions pozwala na p艂ynn膮 komunikacj臋 mi臋dzy komponentami po stronie klienta a logik膮 po stronie serwera.
Konfiguracja projektu Next.js
Zanim zag艂臋bisz si臋 w Route Handlers, upewnij si臋, 偶e masz skonfigurowany projekt Next.js z katalogiem app. Je艣li rozpoczynasz nowy projekt, u偶yj nast臋puj膮cego polecenia:
npx create-next-app@latest my-nextjs-app
Wybierz katalog app podczas procesu konfiguracji, aby w艂膮czy膰 nowy system routingu.
Tworzenie pierwszego Route Handlera
Stw贸rzmy prosty punkt ko艅cowy API, kt贸ry zwraca odpowied藕 w formacie JSON. Utw贸rz nowy katalog wewn膮trz katalogu app, na przyk艂ad /app/api/hello. W tym katalogu utw贸rz plik o nazwie route.ts (lub route.js, je艣li nie u偶ywasz TypeScript).
Oto kod Twojego pierwszego Route Handlera:
// app/api/hello/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Hello from Next.js Route Handlers!' });
}
Wyja艣nienie:
import { NextResponse } from 'next/server';: Importuje obiektNextResponse, kt贸ry jest u偶ywany do konstruowania odpowiedzi API.export async function GET(request: Request) { ... }: Definiuje asynchroniczn膮 funkcj臋, kt贸ra obs艂uguje 偶膮dania GET do punktu ko艅cowego/api/hello. Parametrrequestzapewnia dost臋p do obiektu przychodz膮cego 偶膮dania.return NextResponse.json({ message: 'Hello from Next.js Route Handlers!' });: Tworzy odpowied藕 JSON z wiadomo艣ci膮 i zwraca j膮 za pomoc膮NextResponse.json().
Teraz mo偶esz uzyska膰 dost臋p do tego punktu ko艅cowego, przechodz膮c do /api/hello w przegl膮darce lub u偶ywaj膮c narz臋dzia takiego jak curl lub Postman.
Obs艂uga r贸偶nych metod HTTP
Route Handlers obs艂uguj膮 r贸偶ne metody HTTP, takie jak GET, POST, PUT, DELETE, PATCH i OPTIONS. Mo偶esz zdefiniowa膰 osobne funkcje dla ka偶dej metody w tym samym pliku route.ts.
// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Logic to retrieve all users from the database
const users = [{ id: 1, name: 'John Doe' }, { id: 2, name: 'Jane Smith' }]; // Example data
return NextResponse.json(users);
}
export async function POST(request: Request) {
const data = await request.json(); // Parse the request body as JSON
// Logic to create a new user in the database using 'data'
const newUser = { id: 3, name: data.name, email: data.email }; // Example
return NextResponse.json(newUser, { status: 201 }); // Return the new user with a 201 Created status code
}
Wyja艣nienie:
- Funkcja
GETpobiera list臋 u偶ytkownik贸w (tutaj symulowan膮) i zwraca j膮 jako odpowied藕 JSON. - Funkcja
POSTprzetwarza cia艂o 偶膮dania jako JSON, tworzy nowego u偶ytkownika (symulowanego) i zwraca nowego u偶ytkownika z kodem statusu 201 Created.
Dost臋p do danych 偶膮dania
Obiekt request zapewnia dost臋p do r贸偶nych informacji o przychodz膮cym 偶膮daniu, w tym nag艂贸wk贸w, parametr贸w zapytania i cia艂a 偶膮dania.
Nag艂贸wki
Mo偶esz uzyska膰 dost臋p do nag艂贸wk贸w 偶膮dania za pomoc膮 w艂a艣ciwo艣ci request.headers:
export async function GET(request: Request) {
const userAgent = request.headers.get('user-agent');
console.log('User Agent:', userAgent);
return NextResponse.json({ userAgent });
}
Parametry zapytania
Aby uzyska膰 dost臋p do parametr贸w zapytania, mo偶esz u偶y膰 konstruktora URL:
export async function GET(request: Request) {
const url = new URL(request.url);
const searchParams = new URLSearchParams(url.search);
const id = searchParams.get('id');
console.log('ID:', id);
return NextResponse.json({ id });
}
Cia艂o 偶膮dania
Dla 偶膮da艅 POST, PUT i PATCH mo偶esz uzyska膰 dost臋p do cia艂a 偶膮dania za pomoc膮 metod request.json() lub request.text(), w zale偶no艣ci od typu zawarto艣ci.
export async function POST(request: Request) {
const data = await request.json();
console.log('Data:', data);
return NextResponse.json({ receivedData: data });
}
Zwracanie odpowiedzi
Obiekt NextResponse s艂u偶y do konstruowania odpowiedzi API. Zapewnia kilka metod ustawiania nag艂贸wk贸w, kod贸w statusu i cia艂 odpowiedzi.
Odpowiedzi JSON
U偶yj metody NextResponse.json(), aby zwr贸ci膰 odpowiedzi JSON:
return NextResponse.json({ message: 'Success!', data: { name: 'John Doe' } }, { status: 200 });
Odpowiedzi tekstowe
U偶yj konstruktora new Response(), aby zwr贸ci膰 odpowiedzi w postaci zwyk艂ego tekstu:
return new Response('Hello, world!', { status: 200, headers: { 'Content-Type': 'text/plain' } });
Przekierowania
U偶yj NextResponse.redirect(), aby przekierowa膰 u偶ytkownik贸w na inny adres URL:
import { redirect } from 'next/navigation';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.redirect(new URL('/new-location', request.url));
}
Ustawianie nag艂贸wk贸w
Mo偶esz ustawi膰 niestandardowe nag艂贸wki za pomoc膮 opcji headers w NextResponse.json() lub new Response():
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'no-cache' } });
Integracja z Middleware
Middleware pozwala na uruchomienie kodu przed obs艂u偶eniem 偶膮dania przez Route Handler. Jest to przydatne do uwierzytelniania, autoryzacji, logowania i innych zagadnie艅 przekrojowych.
Aby utworzy膰 middleware, stw贸rz plik o nazwie middleware.ts (lub middleware.js) w katalogu app lub dowolnym podkatalogu. Middleware b臋dzie mia艂o zastosowanie do wszystkich tras w tym katalogu i jego podkatalogach.
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/protected/:path*'], // Apply this middleware to paths starting with /protected/
};
Wyja艣nienie:
- Funkcja
middlewaresprawdza obecno艣膰 tokena uwierzytelniaj膮cego w ciasteczkach 偶膮dania. - Je艣li tokena brakuje, przekierowuje u偶ytkownika na stron臋 logowania.
- W przeciwnym razie pozwala na kontynuowanie 偶膮dania do Route Handlera.
- Obiekt
configokre艣la, 偶e to middleware powinno by膰 stosowane tylko do tras zaczynaj膮cych si臋 od/protected/.
Obs艂uga b艂臋d贸w
Prawid艂owa obs艂uga b艂臋d贸w jest kluczowa dla budowy solidnych interfejs贸w API. Mo偶esz u偶y膰 blok贸w try...catch do obs艂ugi wyj膮tk贸w i zwracania odpowiednich odpowiedzi o b艂臋dach.
export async function GET(request: Request) {
try {
// Simulate an error
throw new Error('Something went wrong!');
} catch (error: any) {
console.error('Error:', error);
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
Wyja艣nienie:
- Blok
try...catchprzechwytuje wszelkie wyj膮tki, kt贸re wyst膮pi膮 wewn膮trz Route Handlera. - W bloku
catchb艂膮d jest logowany, a odpowied藕 o b艂臋dzie jest zwracana z kodem statusu 500 Internal Server Error.
Odpowiedzi strumieniowe
Route Handlers obs艂uguj膮 odpowiedzi strumieniowe, co pozwala na stopniowe wysy艂anie danych do klienta. Jest to szczeg贸lnie przydatne w przypadku du偶ych zbior贸w danych lub d艂ugotrwa艂ych proces贸w.
import { Readable } from 'stream';
import { NextResponse } from 'next/server';
async function* generateData() {
for (let i = 0; i < 10; i++) {
await new Promise(resolve => setTimeout(resolve, 500)); // Simulate delay
yield `Data chunk ${i}\n`;
}
}
export async function GET(request: Request) {
const readableStream = Readable.from(generateData());
return new Response(readableStream, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
}
Wyja艣nienie:
- Funkcja
generateDatato asynchroniczny generator, kt贸ry generuje fragmenty danych z op贸藕nieniem. - Metoda
Readable.from()tworzy czytelny strumie艅 z generatora. - Obiekt
Responsejest tworzony z czytelnym strumieniem jako cia艂em, a nag艂贸wekContent-Typejest ustawiony natext/plain.
Uwierzytelnianie i autoryzacja
Zabezpieczanie punkt贸w ko艅cowych API jest kluczowe. Mo偶esz zaimplementowa膰 uwierzytelnianie i autoryzacj臋 za pomoc膮 middleware lub bezpo艣rednio w swoich Route Handlers.
Uwierzytelnianie
Uwierzytelnianie weryfikuje to偶samo艣膰 u偶ytkownika wysy艂aj膮cego 偶膮danie. Typowe metody uwierzytelniania to:
- JWT (JSON Web Tokens): Generowanie tokena po pomy艣lnym zalogowaniu i weryfikowanie go przy kolejnych 偶膮daniach.
- Uwierzytelnianie oparte na sesji: U偶ywanie ciasteczek do przechowywania identyfikator贸w sesji i weryfikowanie ich przy ka偶dym 偶膮daniu.
- OAuth: Delegowanie uwierzytelniania do dostawcy zewn臋trznego, takiego jak Google czy Facebook.
Oto przyk艂ad uwierzytelniania JWT za pomoc膮 middleware:
// app/middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import jwt from 'jsonwebtoken';
const secret = process.env.JWT_SECRET || 'your-secret-key'; // Replace with a strong, randomly generated secret
export function middleware(request: NextRequest) {
const token = request.cookies.get('auth-token')?.value;
if (!token) {
return NextResponse.json({ message: 'Authentication required' }, { status: 401 });
}
try {
jwt.verify(token, secret);
return NextResponse.next();
} catch (error) {
return NextResponse.json({ message: 'Invalid token' }, { status: 401 });
}
}
export const config = {
matcher: ['/api/protected/:path*'],
};
Autoryzacja
Autoryzacja okre艣la, do jakich zasob贸w u偶ytkownik ma dost臋p. Zazwyczaj opiera si臋 to na rolach lub uprawnieniach.
Mo偶esz zaimplementowa膰 autoryzacj臋 w swoich Route Handlers, sprawdzaj膮c role lub uprawnienia u偶ytkownika i zwracaj膮c b艂膮d, je艣li nie ma on dost臋pu.
// app/api/admin/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
// Assume you have a function to get the user's role from the token or session
const userRole = await getUserRole(request);
if (userRole !== 'admin') {
return NextResponse.json({ message: 'Unauthorized' }, { status: 403 });
}
// Logic to retrieve admin data
const adminData = { message: 'Admin data' };
return NextResponse.json(adminData);
}
async function getUserRole(request: Request): Promise {
// Replace with your actual logic to extract the user's role from the request
// This could involve verifying a JWT token or checking a session
return 'admin'; // Example: hardcoded role for demonstration
}
Wdra偶anie Route Handlers
Route Handlers s膮 wdra偶ane jako funkcje bezserwerowe u wybranego dostawcy hostingu. Next.js obs艂uguje r贸偶ne platformy wdro偶eniowe, w tym Vercel, Netlify, AWS i inne.
W przypadku Vercel wdro偶enie jest tak proste, jak pod艂膮czenie repozytorium Git do Vercel i wypchni臋cie kodu. Vercel automatycznie wykrywa projekt Next.js i wdra偶a Route Handlers jako funkcje bezserwerowe.
Zaawansowane techniki
Funkcje brzegowe (Edge Functions)
Route Handlers mog膮 by膰 wdra偶ane jako funkcje brzegowe (Edge Functions), kt贸re s膮 wykonywane na brzegu sieci CDN, bli偶ej u偶ytkownik贸w. Mo偶e to znacznie zmniejszy膰 op贸藕nienia i poprawi膰 wydajno艣膰.
Aby wdro偶y膰 Route Handler jako funkcj臋 brzegow膮, dodaj 艣rodowisko uruchomieniowe edge do pliku route.ts:
export const runtime = 'edge';
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
return NextResponse.json({ message: 'Hello from the Edge!' });
}
Server Actions
Server Actions pozwalaj膮 na wykonywanie kodu po stronie serwera bezpo艣rednio z komponent贸w React. Route Handlers i Server Actions doskonale ze sob膮 wsp贸艂pracuj膮, umo偶liwiaj膮c 艂atwe tworzenie z艂o偶onych aplikacji.
Oto przyk艂ad u偶ycia Server Action do wywo艂ania Route Handlera:
// app/components/MyComponent.tsx
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
async function handleSubmit(data: FormData) {
'use server';
const name = data.get('name');
const email = data.get('email');
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify({ name, email }),
});
if (response.ok) {
router.refresh(); // Refresh the page to reflect the changes
}
}
export default function MyComponent() {
const router = useRouter();
return (
);
}
Buforowanie (Caching)
Buforowanie mo偶e znacznie poprawi膰 wydajno艣膰 punkt贸w ko艅cowych API. Mo偶esz u偶y膰 nag艂贸wka Cache-Control do kontrolowania, jak odpowiedzi s膮 buforowane przez przegl膮darki i sieci CDN.
return NextResponse.json({ message: 'Success!' }, { status: 200, headers: { 'Cache-Control': 'public, max-age=3600' } });
Ten przyk艂ad ustawia nag艂贸wek Cache-Control na public, max-age=3600, co informuje przegl膮darki i sieci CDN, aby buforowa艂y odpowied藕 przez jedn膮 godzin臋.
Najlepsze praktyki
- U偶ywaj TypeScript: Wykorzystaj bezpiecze艅stwo typ贸w TypeScript do poprawy jako艣ci kodu i zapobiegania b艂臋dom.
- Waliduj 偶膮dania: Waliduj przychodz膮ce 偶膮dania, aby zapewni膰 integralno艣膰 danych i zapobiec z艂o艣liwym danym wej艣ciowym.
- Obs艂uguj b艂臋dy z gracj膮: Zaimplementuj prawid艂ow膮 obs艂ug臋 b艂臋d贸w, aby dostarcza膰 klientom informacyjne komunikaty o b艂臋dach.
- Zabezpiecz swoje punkty ko艅cowe: Zaimplementuj uwierzytelnianie i autoryzacj臋, aby chroni膰 swoje punkty ko艅cowe API.
- U偶ywaj middleware: U偶ywaj middleware do zagadnie艅 przekrojowych, takich jak uwierzytelnianie, logowanie i walidacja 偶膮da艅.
- Buforuj odpowiedzi: U偶ywaj buforowania, aby poprawi膰 wydajno艣膰 swoich punkt贸w ko艅cowych API.
- Monitoruj swoje API: Monitoruj swoje API, aby szybko identyfikowa膰 i rozwi膮zywa膰 problemy.
- Dokumentuj swoje API: Dokumentuj swoje API, aby u艂atwi膰 ich u偶ywanie innym deweloperom. Rozwa偶 u偶ycie narz臋dzi takich jak Swagger/OpenAPI do dokumentacji API.
Przyk艂ady z 偶ycia wzi臋te
Oto kilka przyk艂ad贸w z 偶ycia wzi臋tych, jak mo偶na wykorzysta膰 Route Handlers:
- API e-commerce: Tworzenie punkt贸w ko艅cowych API do zarz膮dzania produktami, zam贸wieniami i u偶ytkownikami.
- API medi贸w spo艂eczno艣ciowych: Tworzenie punkt贸w ko艅cowych API do publikowania post贸w, obserwowania u偶ytkownik贸w i pobierania osi czasu.
- API systemu zarz膮dzania tre艣ci膮 (CMS): Tworzenie punkt贸w ko艅cowych API do zarz膮dzania tre艣ci膮, u偶ytkownikami i ustawieniami.
- API analityki danych: Tworzenie punkt贸w ko艅cowych API do zbierania i analizowania danych. Na przyk艂ad, Route Handler m贸g艂by odbiera膰 dane z pikseli 艣ledz膮cych na r贸偶nych stronach internetowych i agregowa膰 te informacje do cel贸w raportowania.
Przyk艂ad mi臋dzynarodowego e-commerce: Route Handler u偶ywany do pobierania cen produkt贸w na podstawie kraju u偶ytkownika. Punkt ko艅cowy m贸g艂by wykorzysta膰 geolokalizacj臋 偶膮dania (pochodz膮c膮 z adresu IP) do okre艣lenia lokalizacji u偶ytkownika i zwr贸cenia cen w odpowiedniej walucie. Przyczynia si臋 to do zlokalizowanego do艣wiadczenia zakupowego.
Przyk艂ad globalnego uwierzytelniania: Route Handler implementuj膮cy uwierzytelnianie wielosk艂adnikowe (MFA) dla u偶ytkownik贸w na ca艂ym 艣wiecie. Mog艂oby to obejmowa膰 wysy艂anie kod贸w SMS lub korzystanie z aplikacji uwierzytelniaj膮cych, z poszanowaniem przepis贸w dotycz膮cych prywatno艣ci i infrastruktury telekomunikacyjnej r贸偶nych region贸w.
Dostarczanie tre艣ci wieloj臋zycznych: Route Handler dostarczaj膮cy tre艣膰 w preferowanym j臋zyku u偶ytkownika. Mo偶na to okre艣li膰 na podstawie nag艂贸wka `Accept-Language` w 偶膮daniu. Ten przyk艂ad podkre艣la potrzeb臋 prawid艂owego kodowania UTF-8 i wsparcia dla j臋zyk贸w pisanych od prawej do lewej, w stosownych przypadkach.
Podsumowanie
Next.js Route Handlers zapewniaj膮 pot臋偶ny i elastyczny spos贸b tworzenia punkt贸w ko艅cowych API bezpo艣rednio w aplikacji Next.js. Wykorzystuj膮c Route Handlers, mo偶na z 艂atwo艣ci膮 budowa膰 solidne interfejsy API, umieszcza膰 logik臋 backendow膮 obok komponent贸w React i korzysta膰 z funkcji takich jak middleware, streaming i Edge Functions.
Ten kompleksowy przewodnik om贸wi艂 wszystko, od podstawowej konfiguracji po zaawansowane techniki. Post臋puj膮c zgodnie z najlepszymi praktykami opisanymi w tym przewodniku, mo偶esz tworzy膰 wysokiej jako艣ci interfejsy API, kt贸re s膮 bezpieczne, wydajne i 艂atwe w utrzymaniu.